#ifndef __CALC_H
#define __CALC_H

#include <string>
#include <set>
#include <map>
#include "number.h"
#include "parser.h"
#include "defs.h"

using namespace std;

/** Calculator that computes the result of a one-line expression.
 *
 **/
class Calc {
  protected: 
    /** Input line to be calculated.
     * Received in constructor and unchanged afterwards.
     */
    string input;
    /** Message related to parse failure.
     * Whenever parsing error occurs, this message is set and parse returns 
     * false.
     *
     * @see #parse()
     */
    string message;
    /** The result of the calculation.
     * Type is defined in defs.h
     */
    RESULT result;

    /** A shortcut method to iterate over parsers.
     *
     * @param input A redundant parameter.
     * @param pos   Start position for parsing. The position is updated during 
     *		    the parsing process.
     *		
     * @return pointer to an allocated number. Must be freed after processing.
     */
    Number *parseNum(string input, size_t &pos);
    /** An internal set of parser pointers.
     * Parser is abstract, this set obviously contains instances of derived 
     * classes.
     */
    static set<Parser *> parsers;
    /** An internal map of operator precedence.
     * This is one thing to adjust if a new operator is added.
     */
    static map<char, int> op_precedence;

  public:
    /** Parses string for an operator, with all available parsers.
     * This must be public and static so that other parsers may rely on it, 
     * even if the parsers are mixed (e.g. language num with native op)
     *
     * @param input the string to be parsed
     * @param pos   the starting position for parsing.
     */
    char parseOp(string input, size_t &pos);
    /** The "ALL KLEAR" result of parsing. 
     * Should be accompanied with a true return value of the parse method.
     *
     * @see #parse()
     */
    static const string MSG_OK;
    /** Creates calculator for input string.
     * The string is not changed afterwards.
     *
     * @param in The string to be parsed.
     */
    Calc(string in);

    /** Parses the expression for error and calculates the result.
     * The tokens (numbers and operations) in the expression can be of any 
     * language that is defined (and loaded).
     *
     * The result is stored as a long double precision (see RESULT) number.
     * 
     * @return 
     *	    Upon successful parsing, the message is set to MSG_OK and true is 
     *	    returned.
     *	    Upon parse error (including arithmetic error) message is set to 
     *	    an appropriate message and false is returned.
     *
     * @see MSG_OK
     */
    bool parse();

    /** Returns the message of parsing.
     *
     * @return The last message received on parsing.
     *
     * @see parse
     */
    const string getMessage();

    /** Returns the result of the expression. */
    const RESULT getResult();

    /** Loads all available parsers.
     * Find all parsers in the parser directory (defaults to same as executable
     * path) and creates the parser entries for each.
     *
     */
    static void loadParsers();
};

#endif
